/**
 * 点赞和取消点赞行为需要在三个对象中存储
 * 1.对象本身有个 praiseCount记录此对象的点赞总数，也可以通过记录二进行维度统计(推荐后者方式，前者需要维护两张表）
 * 2.一个对象存储 点赞对象和点赞用户的记录，通过此记录可以表示目标项是否被当前用户点赞过，另外可以以此进行用户和目标项两个维度进行统计
 * 3.一个日志对象，记录哪个用户在什么时候对哪个对象进行了什么操作，并可以用于以时间范围内进行统计
 */

var praiseHelper = {
  /**
   *存储点赞的人和用户
   */
  praiseData: [],
  /**
   * 存储点赞记录
   */
  praiseLog: [],
  /**
   * 查询点赞数据
   * @param {*} itemId
   * @param {*} userId
   */
  queryPraiseData: function (itemId, userId) {
    var target = null;
    this.praiseData.forEach((item) => {
      if (item.itemId === itemId && item.userId === userId) {
        target = item;
      }
    });
    return target;
  },
  /**
   *
   * @param {*} itemId
   * @param {*} userId
   */
  addPraiseRecord: function (itemId, userId) {
    var record = this.queryPraiseData(itemId, userId);
    if (record === null) {
      record = { itemId, userId };
    }
    this.praiseData.push(record);
  },
  /**
   *
   * @param {*} itemId
   * @param {*} userId
   */
  cancelPraiseRecord: function (itemId, userId) {
    var item = this.queryPraiseData(itemId, userId);
    if (item === null) {
      throw new Error("no praise action");
    }
    this.praiseData = this.praiseData.filter(
      (record) => !(record.itemId === itemId && record.userId === userId)
    );
  },
  /**
   *
   * @param {*} itemId
   * @param {*} userId
   */
  hasPraised: function (itemId, userId) {
    var item = this.queryPraiseData(itemId, userId);
    return item !== null;
  },
  /**
   *
   * @param {*} itemId
   * @param {*} userId
   * @param {*} action
   */
  addPraiseLog: function (itemId, userId, action) {
    var obj = {
      itemId,
      userId,
      action,
      operationTime: new Date(),
      toString: function () {
        return (
          this.operationTime.toLocaleString() +
          " 用户 " +
          this.userId +
          " 对项 " +
          this.itemId +
          "进行了" +
          this.action +
          "操作"
        );
      },
    };
    this.praiseLog.push(obj);
  },
  /**
   *
   * @param {*} itemId
   */
  getPraiseUsersForItem: function (itemId) {
    return this.praiseData.filter((d) => d.itemId === itemId);
  },
  /**
   *
   * @param {*} userId
   */
  getPraiseItemsForUser: function (userId) {
    return this.praiseData.filter((d) => d.userId === userId);
  },
  /**
   *
   * @param {*} itemId
   */
  getPraiseCountByItemId: function (itemId) {
    return this.getPraiseUsersForItem(itemId).length;
  },
  /**
   *
   * @param {*} userId
   */
  getPraiseCountByUserId: function (userId) {
    return this.getPraiseItemsForUser(userId).length;
  },
  /**
   *
   * @param {*} targetItem
   * @param {*} actionUser
   */
  togglePraise: function (targetItem, actionUser) {
    var itemId = targetItem.id;
    var userId = actionUser.id;
    var hasPraised = this.hasPraised(itemId, userId);
    if (hasPraised) {
      this.cancelPraiseRecord(itemId, userId);
      this.addPraiseLog(itemId, userId, "cancel-praise");
    } else {
      this.addPraiseRecord(itemId, userId);
      this.addPraiseLog(itemId, userId, "praise");
    }
  },
};

var items = [
  {
    id: "001",
    name: "item1",
  },
  {
    id: "002",
    name: "item2",
  },
  {
    id: "003",
    name: "item3",
  },
];

var users = [
  {
    id: "001",
    name: "user1",
  },
  {
    id: "002",
    name: "user2",
  },
  {
    id: "003",
    name: "user3",
  },
];

var appendPraiseDataForItems = function () {
  items.forEach((item) => {
    item.praiseCount = praiseHelper.getPraiseCountByItemId(item.id);
    var userIds = praiseHelper
      .getPraiseUsersForItem(item.id)
      .map((u) => u.userId);
    item.praiseUsers = userIds.map((id) => users.find((u) => u.id === id));
  });
};

var appendPraiseDataForUsers = function () {
  users.forEach((user) => {
    user.praiseCount = praiseHelper.getPraiseCountByUserId(user.id);
    var itemIds = praiseHelper
      .getPraiseItemsForUser(user.id)
      .map((i) => i.itemId);
    user.praiseItems = itemIds.map((id) => items.find((i) => i.id === id));
  });
};

var refreshData = function () {
  appendPraiseDataForItems();
  appendPraiseDataForUsers();

  console.log("users", users);
  console.log("items", items);
  console.log("操作日志：");
  praiseHelper.praiseLog.forEach((x) => console.log(x.toString()));
};

praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[1], users[0]);
praiseHelper.togglePraise(items[2], users[0]);
praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[0], users[1]);
praiseHelper.togglePraise(items[1], users[1]);
praiseHelper.togglePraise(items[1], users[2]);
praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[0], users[0]);
praiseHelper.togglePraise(items[0], users[0]);
refreshData();
